package com.czh.subject.domain.service.impl;


import com.czh.subject.common.entity.PageResult;
import com.czh.subject.common.enums.SubjectIsDeleteEnum;
import com.czh.subject.common.enums.SubjectStatusEnum;
import com.czh.subject.common.utils.StringUtil;
import com.czh.subject.common.utils.UserUtil;
import com.czh.subject.domain.convert.SubjectLikedBOConverter;
import com.czh.subject.domain.entity.SubjectLikedBO;
import com.czh.subject.domain.redis.RedisUtil;
import com.czh.subject.domain.service.SubjectLikedDomainService;
import com.czh.subject.infra.basic.entity.SubjectInfo;
import com.czh.subject.infra.basic.entity.SubjectLiked;
import com.czh.subject.infra.basic.service.SubjectInfoService;
import com.czh.subject.infra.basic.service.SubjectLikedService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


/**
 * 题目点赞表 领域service实现
 *
 * @author caozaihui
 * @since 2024-09-14 11:31:23
 */
@Service
@Slf4j
public class SubjectLikedDomainServiceImpl implements SubjectLikedDomainService {

    @Resource
    private SubjectLikedService subjectLikedService;
    @Resource
    private SubjectInfoService subjectInfoService;
    @Resource
    private RedisUtil redisUtil;

    public final String LIKED_STATUS_KEY = "subject.liked";

    public final String LIKED_COUNT_KEY = "subject.liked.count";

    @Override
    public Boolean add(SubjectLikedBO subjectLikedBO) {
        try {
            String likedCountKey = StringUtil.buildKey(".", LIKED_COUNT_KEY, subjectLikedBO.getSubjectId().toString());
            String likedStatusMapKey = StringUtil.buildKey(":", String.valueOf(subjectLikedBO.getSubjectId()), subjectLikedBO.getLikeUserId());
            Integer status = subjectLikedBO.getStatus();
            // 更新点赞状态
            redisUtil.setCacheMapValue(LIKED_STATUS_KEY, likedStatusMapKey, status);
            // 点赞
            if (status == SubjectStatusEnum.STATUS.getCode()
                    && subjectLikedBO.getSubjectId() != null
                    && isLiked(String.valueOf(subjectLikedBO.getSubjectId()), subjectLikedBO.getLikeUserId())) {
                redisUtil.setCacheObjectIncr(likedCountKey, 1);
            } else if (status == SubjectStatusEnum.NO_STATUS.getCode()) {
                // 取消点赞
                try {
                    Object cacheObject = redisUtil.getCacheObject(likedCountKey);
                    if (cacheObject != null) {
                        int count = Integer.parseInt(cacheObject.toString());
                        if (count <= 0) {
                            log.error("{}: 点赞数为0或不存在", subjectLikedBO.getSubjectId());
                        } else {
                            redisUtil.setCacheObjectIncr(likedCountKey, -1);
                        }
                    }
                } catch (NumberFormatException e) {
                    log.error("将缓存对象转换为整数时发生错误: {}", e.getMessage(), e);
                }
            }
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public Boolean isLiked(String subjectId, String userId) {
        Object status = redisUtil.getCacheMapValue(LIKED_STATUS_KEY, StringUtil.buildKey(":", subjectId, userId));
        if (Objects.isNull(status)) {
            SubjectLiked subjectLiked = new SubjectLiked();
            subjectLiked.setLikeUserId(userId);
            subjectLiked.setSubjectId(Long.valueOf(subjectId));
            subjectLiked.setIsDeleted(SubjectIsDeleteEnum.NO_DELETED.getCode());
            List<SubjectLiked> subjectLikedList = subjectLikedService.querySubjectLikedList(subjectLiked);
            //重新放入缓存
            boolean temp = subjectLikedList.stream().
                    anyMatch(itemSubjectLiked -> itemSubjectLiked.getStatus() == SubjectStatusEnum.STATUS.getCode());
            redisUtil.setCacheMapValue(LIKED_STATUS_KEY, StringUtil.buildKey(":", subjectId, userId), temp ? 1 : 0);
            return temp;
        }
        return status.equals(SubjectStatusEnum.STATUS.getCode());
    }

    /**
     * TODO 当缓存中不存在时候要查询数据库(完成)
     */
    @Override
    public Integer getLikedCount(String subjectId) {
        String likedCountKey = StringUtil.buildKey(".", LIKED_COUNT_KEY, subjectId);
        Object cacheObject = redisUtil.getCacheObject(likedCountKey);
        int count;
        if (Objects.nonNull(cacheObject)) {
            count = Integer.parseInt(cacheObject.toString());
        } else {
            SubjectLiked subjectLiked = new SubjectLiked();
            subjectLiked.setSubjectId(Long.valueOf(subjectId));
            subjectLiked.setStatus(SubjectStatusEnum.STATUS.getCode());
            count = subjectLikedService.querySubjectLikedCount(subjectLiked);
            redisUtil.setCacheObject(likedCountKey, count, 10, TimeUnit.MINUTES);
        }
        return count;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void asyncLiked() {
        Map<Object, Object> likedList = redisUtil.getCacheMap(LIKED_STATUS_KEY);
        if (MapUtils.isEmpty(likedList)) {
            return;
        }
        List<SubjectLiked> subjectLikeList = new LinkedList<>();
        likedList.forEach((key, value) -> {
            if (Objects.nonNull(key) && Objects.nonNull(value)) {
                String[] subjectAndUserId = key.toString().split(":");
                String subjectId = subjectAndUserId[0];
                String userId = subjectAndUserId[1];
                SubjectLiked subjectLiked = new SubjectLiked();
                subjectLiked.setSubjectId(Long.valueOf(subjectId));
                subjectLiked.setLikeUserId(userId);
                subjectLiked.setStatus(Integer.parseInt(value.toString()));
                subjectLikeList.add(subjectLiked);
            }
        });
        //批量插入或者更新数据
        subjectLikedService.batchInsert(subjectLikeList);
        boolean b = redisUtil.deleteObject(LIKED_STATUS_KEY);
        if (!b) {
            log.error("删除Redis点赞记录{}失败", LIKED_STATUS_KEY);
        }
    }

    @Override
    public PageResult<SubjectLikedBO> getMineSubjectLikedPage(SubjectLikedBO subjectLikedBO) {
        PageResult<SubjectLikedBO> pageResult = new PageResult<>();
        pageResult.setPageNo(subjectLikedBO.getPageNo());
        pageResult.setPageSize(subjectLikedBO.getPageSize());

        //查询点赞列表
        int start = (subjectLikedBO.getPageNo() - 1) * subjectLikedBO.getPageSize();
        SubjectLiked subjectLiked = SubjectLikedBOConverter.INSTANCE.convert(subjectLikedBO);
        subjectLiked.setLikeUserId(UserUtil.getUserId());
        subjectLiked.setStatus(SubjectStatusEnum.STATUS.getCode());
        subjectLiked.setIsDeleted(SubjectIsDeleteEnum.NO_DELETED.getCode());

        List<SubjectLiked> subjectLikedList = subjectLikedService.querySubjectLikedPage(subjectLiked, start, subjectLikedBO.getPageSize());
        List<SubjectLikedBO> subjectLikedResult = SubjectLikedBOConverter.INSTANCE.convert(subjectLikedList);

        //查询题目信息
        Map<Long, String> SubjectInfoMap = subjectInfoService.querySubjectIInfoByIds(subjectLikedResult.stream().map(SubjectLikedBO::getSubjectId).toList()).
                stream().collect(Collectors.toMap(SubjectInfo::getId, SubjectInfo::getSubjectName, (v1, v2) -> v2));

        subjectLikedResult.forEach(item -> item.setSubjectName(SubjectInfoMap.get(item.getSubjectId())));
        pageResult.setTotal(subjectLikedResult.size());
        pageResult.setResult(subjectLikedResult);
        return pageResult;
    }
}
